/*
 * =====================================================================================
 * Copyright (C) 2024 Ingenic Semiconductor Co.,Ltd
 * All Rights Reserved
 *
 * Filename     : gpio.c
 * Author       : Keven <keven.ywhan@ingenic.com>
 * Created      : 2024/06/04 16:24
 * Description  :
 *
 * =====================================================================================
 */

#include "common/reg_gpio.h"
#include "gpio.h"

static inline uint32_t is_gpio_from_chip(uint32_t gpio_num)
{
	return gpio_num < (GPIO_NR_PORTS * 32) ? 1 : 0;
}

uint32_t gpio_request(uint32_t gpio, const char *label)
{
	return gpio;
}

int32_t gpio_free(uint32_t gpio)
{
	return 0;
}

void gpio_port_set_value(enum gpio_port port, uint32_t pin, uint32_t value)
{
	if (value)
		writel(1 << pin, GPIO_PXPAT0S(port));
	else
		writel(1 << pin, GPIO_PXPAT0C(port));
}

void gpio_port_direction_input(enum gpio_port port, uint32_t pin)
{
	writel(1 << pin, GPIO_PXINTC(port));
	writel(1 << pin, GPIO_PXMSKS(port));
	writel(1 << pin, GPIO_PXPAT1S(port));
}

void gpio_port_direction_output(enum gpio_port port, uint32_t pin, uint32_t value)
{
	writel(1 << pin, GPIO_PXINTC(port));
	writel(1 << pin, GPIO_PXMSKS(port));
	writel(1 << pin, GPIO_PXPAT1C(port));

	gpio_port_set_value(port, pin, value);
}

int32_t gpio_set_value(uint32_t gpio, uint32_t value)
{
	uint32_t port = gpio / 32;
	uint32_t pin = gpio % 32;
	if(is_gpio_from_chip(gpio)) {
		gpio_port_set_value(port, pin, value);
	}

	return 0;
}

int32_t gpio_get_value(uint32_t gpio)
{
	uint32_t port = gpio / 32;
	uint32_t pin = gpio % 32;
	if(is_gpio_from_chip(gpio)) {
		return !!(readl(GPIO_PXPIN(port)) & (1 << pin));
	}

	return 0;
}

int32_t gpio_direction_input(uint32_t gpio)
{
	uint32_t port = gpio / 32;
	uint32_t pin = gpio % 32;
	if(is_gpio_from_chip(gpio)) {
		gpio_port_direction_input(port, pin);
	}
	return 0;
}

int32_t gpio_direction_output(uint32_t gpio, uint32_t value)
{
	uint32_t port = gpio / 32;
	uint32_t pin = gpio % 32;
	if(is_gpio_from_chip(gpio)) {
		gpio_port_direction_output(port, pin, value);
	}
	return 0;
}

void gpio_set_func(enum gpio_port port, enum gpio_function func, uint32_t pins)
{

	writel(func & 0x8? pins : 0, GPIO_PXINTS(port));
	writel(func & 0x4? pins : 0, GPIO_PXMSKS(port));
	writel(func & 0x2? pins : 0, GPIO_PXPAT1S(port));
	writel(func & 0x1? pins : 0, GPIO_PXPAT0S(port));

	writel(func & 0x8? 0 : pins, GPIO_PXINTC(port));
	writel(func & 0x4? 0 : pins, GPIO_PXMSKC(port));
	writel(func & 0x2? 0 : pins, GPIO_PXPAT1C(port));
	writel(func & 0x1? 0 : pins, GPIO_PXPAT0C(port));

}

